home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ASME's Mechanical Engine…ing Toolkit 1997 December
/
ASME's Mechanical Engineering Toolkit 1997 December.iso
/
c_lang
/
bituudec.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-12-23
|
7KB
|
274 lines
/* bituudec.c */
/* Exit status values:
1 Unable to open input file.
2 Removed, used to indicate more than one argument.
3 No begin line, probably not a uuencoded file.
4 Unable to write output file.
5 Missing an end line, file may be truncated?
10 Short file, EOF reached while decoding.
*/
/* Modified version of uudecode by Mark S. Zinzow
in IBM C or MSC V. 2 use
clink bituudec ssetargv;
to get DOS command line wildcard processing */
#ifndef lint
static char sccsid[] = "@(#)bituudecode.c 6.0 (Berkeley & M.S.Z.) 3/22/87"
#endif
/*
* uudecode [input]
*
* create the specified file, decoding as you go.
* used with uuencode.
*/
#include <stdio.h>
#ifndef MSDOS
#include <pwd.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
/* single character decode */
#define DEC(c) (((c) - ' ') & 077)
main(argc, argv)
char **argv;
{
FILE *in;
/* M.S.Z. 3/22/87
The following code block was deleted to support decoding of multiple
files with the use of wild cards or several command line filenames.
Part of the main line was moved to the function uufile with the
appropriate changes for repeating for several files.
*/
/* optional input arg M.S.Z why only one file?
if (argc > 1) {
if ((in = fopen(argv[1], "r")) == NULL) {
perror(argv[1]);
exit(1);
}
argv++; argc--;
} else
in = stdin;
if (argc != 1) {
printf("Usage: uudecode [infile]\n");
exit(2);
} */
if (argc == 1) /* no args; copy standard input */
uufile(stdin);
else
while (--argc > 0)
if ((in = fopen(*++argv, "r")) == NULL) {
perror(*argv);
exit(1);
} else {
uufile(in);
fclose(in);
}
exit(0);
}
uufile(in) /* Process one input file M.S.Z. */
FILE *in;
{
FILE *out;
struct stat sbuf;
int mode, filect=0;
char dest[128];
char buf[80];
while ( !feof(in) ) { /* added while and filect for status */
/* search for header line */
for (;;) {
if (fgets(buf, sizeof buf, in) == NULL) {
if (filect < 1) {
fprintf(stderr, "No begin line\n");
exit(3);
}
else
return;
}
if (strncmp(buf, "begin ", 6) == 0)
break;
}
sscanf(buf, "begin %o %s", &mode, dest);
fprintf(stderr,
"Processing file %d \"%s\", in current source file.\n",
++filect,dest);
/* handle ~user/file format */
#ifndef MSDOS
if (dest[0] == '~') {
char *sl;
struct passwd *getpwnam();
char *index();
struct passwd *user;
char dnbuf[100];
sl = index(dest, '/');
if (sl == NULL) {
fprintf(stderr, "Illegal ~user\n");
exit(3);
}
*sl++ = 0;
user = getpwnam(dest+1);
if (user == NULL) {
fprintf(stderr, "No such user as %s\n", dest);
exit(4);
}
strcpy(dnbuf, user->pw_dir);
strcat(dnbuf, "/");
strcat(dnbuf, sl);
strcpy(dest, dnbuf);
}
#endif
/* create output file */
#ifdef MSDOS
/* binary output file */
out = fopen(dest, "wb");
#else
out = fopen(dest, "w");
#endif
if (out == NULL) {
perror(dest);
exit(4);
}
chmod(dest, mode);
decode(in, out);
if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {
fprintf(stderr, "No end line\n");
exit(5);
}
fclose(out);
}
}
/*
* copy from in to out, decoding as you go along.
*/
decode(in, out)
FILE *in;
FILE *out;
{
char buf[80];
char *bp;
int n,j,k,l; /* M.S.Z. added jkl for a counters in padding spaces */
for (;;) {
/* for each input line */
if (fgets(buf, sizeof buf, in) == NULL) {
printf("Short file\n");
exit(10);
}
n = DEC(buf[0]);
/* was
if (n <= 0)
break;
*/
if (buf[0] <= ' ')
break;
/* M.S.Z. What good does it do to test n<0 when in DEC the sign bits are
masked off?
This seems to allow us to just ignore blank lines.
A blank line (just \n) before the final end used to cause
a short file error message, now that's not a problem.
Next I'm adding a kludge to tack trailing spaces back on the input lines: */
j = strlen(buf);
k = n*4/3 + 2 ; /* add 1 for \n and 1 for the first count char
if ( j < k )
for( l=j-1 ; l < k && l < sizeof buf ; l++ ) buf[l] = '
/* Ignore that this changes the \n to a ' ';
that doesn't hurt. M.S.Z. */
/* M.S.Z. end kludge */
bp = &buf[1];
while (n > 0) {
outdec(bp, out, n);
bp += 4;
n -= 3;
}
}
}
/*
* output a group of 3 bytes (4 input characters).
* the input chars are pointed to by p, they are to
* be output to file f. n is used to tell us not to
* output all of them at the end of the file.
*/
outdec(p, f, n)
char *p;
FILE *f;
{
int c1, c2, c3;
c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
c3 = DEC(p[2]) << 6 | DEC(p[3]);
if (n >= 1)
putc(c1, f);
if (n >= 2)
putc(c2, f);
if (n >= 3)
putc(c3, f);
/* M.S.Z. Another problem. Nobody notices when the disk is full! */
if (ferror(f)) {
perror("Write error");
exit(4);
}
/* M.S.Z. end another hack */
}
/* fr: like read but stdio */
int
fr(fd, buf, cnt)
FILE *fd;
char *buf;
int cnt;
{
int c, i;
for (i=0; i<cnt; i++) {
c = getc(fd);
if (c == EOF)
return(i);
buf[i] = c;
}
return (cnt);
}
/*
* Return the ptr in sp at which the character c appears;
* NULL if not found
*/
#define NULL 0
char *
index(sp, c)
register char *sp, c;
{
do {
if (*sp == c)
return(sp);
} while (*sp++);
return(NULL);
}